using System;
using System.Collections.Generic;
using System.ComponentModel;
using CS6238Project2.Banking.Commerce;
using System.Security.Cryptography.Xml;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Serialization;


namespace CS6238Project2.Banking.Communication
{   
    /// <summary>
    /// Object contains a variety of data.  Encapsulates all possible
    /// information users would want to express to one another.  Some
    /// properties are automatically encrypted.  Care must be taken
    /// with the Authorization property.  To be sent across the net,
    /// should be serialized with XML.  
    /// </summary>
    [Serializable]
    [XmlRootAttribute(IsNullable=true)] 
    public class Parcel
    {
        private Certificate certificate;
        private string sender;
        private string receiver;
        private string returnAddress;
        private string senderAddr;
        private int senderPort;
        private XmlDocument secureData;
        private Transaction transaction;
        private Transaction merchantTransaction;
        private XmlDocument purchase;
        private XmlDocument authorization;
        private BindingList<Entity.AddressEntry> nameList;
        private Account account;
        private BindingList<Good> inventoryList;
        private int number;
        private string messageData;
        private string type;



        /// <summary>
        /// Initializes all members to null.
        /// </summary>
        public Parcel()
        {
            certificate = new Certificate();
            sender = "";
            receiver = "";
            secureData = new XmlDocument();
            transaction = new Transaction();
            merchantTransaction = new Transaction();
            purchase = new XmlDocument();
            authorization = new XmlDocument();
            messageData = "";
            type = "";
        }

        public Parcel(Parcel parcel)
        {
            this.certificate= parcel.certificate;
            this.sender = parcel.sender;
            this.receiver = parcel.receiver;
            this.returnAddress = parcel.returnAddress;
            this.senderAddr  = parcel.senderAddr;
            this.senderPort  = parcel.senderPort;
            this.secureData = parcel.secureData;
            this.transaction  = parcel.transaction;
            this.merchantTransaction  = parcel.merchantTransaction;
            this.purchase  = parcel.purchase;
            this.authorization = parcel.authorization;
            this.nameList  = parcel.nameList;
            this.account = parcel.account;
            this.inventoryList = parcel.inventoryList;
            this.number  = parcel.number;
            this.messageData = parcel.messageData;
            this.type = parcel.type;
        }

        /// <summary>
        /// Parcel for Initializing registration
        /// </summary>
        /// <param name="send">Sender of the package</param>
        /// <param name="recv">Receiver of the Package</param>
        /// <param name="typ">Probably "Registration Request"</param>
        public Parcel(string send, string recv, string typ)
        {
            sender = send;
            receiver = recv;
            type = typ;
        }

        /// <summary>
        /// The string represents the type of parcel this may be.
        /// Valid types include Transaction, Transaction Response,
        /// Registration Request, Registration Response, Dual Transaction, 
        /// Dual Transaction Response, Approved, Not Approved, and various
        /// others.
        /// </summary>
        [XmlElement(IsNullable = true)]
        public string Type
        {
            get { return type; }
            set { type = value; }
        }

        /// <summary>
        /// A string which contains a variety of message data
        /// which allows the communication of events throughout
        /// the system.
        /// </summary>
        [XmlElement(IsNullable = true)]
        public string MessageData
        {
            get { return messageData; }
            set { messageData = value; }
        }


        /// <summary>
        /// Should be stored in encrypted form, is the authority
        /// that is delegated from one user to another, to be
        /// verified by a third party.  The key inside this 
        /// encrypted certificate cannot be encrypted, so will be lost
        /// if put inside.
        /// </summary>
        [XmlElement(IsNullable = true)]
        public XmlDocument Authorization
        {
            get { return authorization; }
            set { authorization = value; }
        }

        /// <summary>
        /// Gets the transaction that's been encrypted
        /// </summary>
        /// <returns></returns>
        public Certificate d_Authorization()
        {
            XmlDocument tempDoc = authorization.Clone() as XmlDocument;
            return (Certificate)Tools.Encryption.ObjectifyXml
                (tempDoc, typeof(Certificate), certificate.Token);
        }


        public void e_Authorization(Certificate cert)
        {
            authorization = Tools.Encryption.Encrypt(cert, certificate.Token);
        }

        


        /// <summary>
        /// The purchase included in the parcel is stored in
        /// encrypted form unless no key present, in which case
        /// it is stored in XML plaintext.
        /// </summary>
        [XmlElement(IsNullable = true)]
        public XmlDocument Purchase
        {
            get { return purchase; }
            set { purchase = value; }
        }


        /// <summary>
        /// Gets the transaction that's been encrypted
        /// </summary>
        /// <returns></returns>
        public Purchase d_Purchase()
        {
            XmlDocument tempDoc = purchase.Clone() as XmlDocument;
            return (Purchase)Tools.Encryption.ObjectifyXml
                (tempDoc, typeof(Purchase), certificate.Token);
        }


        public void e_Purchase(Purchase purch)
        {
            purchase = Tools.Encryption.Encrypt(purch, certificate.Token);
        }



        /// <summary>
        /// A transaction is stored in encrypted form, if a token is given.
        /// Otherwise, if the token is null, its stored in plaintext
        /// as an XML string
        /// </summary>
        [XmlElement(IsNullable = true)]
        public Transaction Transaction
        {
            get
            { return transaction; }
            set
            { transaction = value; }
        }
        /*
        /// <summary>
        /// Gets the transaction that's been encrypted
        /// </summary>
        /// <returns></returns>
        public Transaction d_Transaction()
        {
            XmlDocument tempDoc = transaction.Clone() as XmlDocument;
            return (Transaction)Tools.Encryption.ObjectifyXml
                (tempDoc, typeof(Transaction), certificate.Token);
        }


        public void e_Transaction(Transaction transact)
        {
            transaction = Tools.Encryption.Encrypt(transact, certificate.Token);
        }*/


        /// <summary>
        /// A merchant transaction is specifically for a dual transaction
        /// when a merchant sends its own and the user's transaction. Stored
        /// Encrypted or plaintext if token is null.
        /// </summary>
        [XmlElement(IsNullable = true)]
        public Transaction MerchantTransaction
        {
            get { return merchantTransaction; }
            set { merchantTransaction = value; }
        }
        /*

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public Transaction d_MerchantTransaction()
        {
            XmlDocument tempDoc = merchantTransaction.Clone() as XmlDocument;
            return (Transaction)Tools.Encryption.ObjectifyXml
                (tempDoc, typeof(Transaction), certificate.Token);
        }


        public void e_MerchantTransaction(Transaction transact)
        {
            merchantTransaction = Tools.Encryption.Encrypt(transact, certificate.Token);
        }*/


        /// <summary>
        /// The certificate of the parcel is used to encrypt all stored data
        /// </summary>
        [XmlElement(IsNullable = true)]
        public Certificate Certificate
        {
            get { return certificate; }
            set { certificate = value; }
        }

        /// <summary>
        /// The sender of the parcel.
        /// </summary>
        [XmlElement(IsNullable = true)]
        public string Sender
        {
            get { return sender; }
            set { sender = value; }
        }
        /// <summary>
        /// The receiver of the parcel-- all users should reject
        /// the parcel if they are not the receiver.
        /// </summary>
        [XmlElement(IsNullable = true)]
        public string Receiver
        {
            get { return receiver; }
            set { receiver = value; }
        }
        public string SenderAddr
        {
            get { return senderAddr; }
            set { senderAddr = value; }
        }
        public int SenderPort
        {
            get { return senderPort; }
            set { senderPort = value; }
        }

        /// <summary>
        /// The Original creator of the parcel should sign this
        /// so that a response will come back to them.  Need not
        /// be encrypted, as it's not a physical address, just
        /// a digital one.
        /// </summary>
        public string Source
        {
            get { return returnAddress; }
            set { returnAddress = value; }
        }

       

        /// <summary>
        /// Used to hold various other data that the parcel might be transmitting.
        /// </summary>
        public BindingList<Entity.AddressEntry> NameList
        {
            get { return nameList; }
            set { nameList = value; }
        }
        /// <summary>
        /// Used to hold various other data that the parcel might be transmitting.
        /// </summary>
        public Account Account
        {
            get { return account; }
            set { account = value; }
        }

        /// <summary>
        /// Used to hold various other data that the parcel might be transmitting.
        /// </summary>
        public BindingList<Good> InventoryList
        {
            get { return inventoryList; }
            set { inventoryList = value; }
        }

        /// <summary>
        /// A general purpose number for transmitting unimportant data.
        /// </summary>
        public int Number
        {
            get { return number; }
            set { number = value; }
        }

    }
}
